package com.xvyy.tingshu.order.service.impl;

import java.util.Date;

import com.xvyy.tingshu.common.rabbit.constant.MqConst;
import com.xvyy.tingshu.common.rabbit.service.RabbitService;
import com.xvyy.tingshu.common.result.ResultCodeEnum;
import com.xvyy.tingshu.model.order.LocalMsg;
import com.xvyy.tingshu.model.order.OrderDerate;
import com.xvyy.tingshu.model.order.OrderDetail;
import com.xvyy.tingshu.order.adapter.OrderDealTypeAdapter;
import com.xvyy.tingshu.order.mapper.LocalMsgMapper;
import com.xvyy.tingshu.order.mapper.OrderDerateMapper;
import com.xvyy.tingshu.order.mapper.OrderDetailMapper;
//import com.xvyy.tingshu.order.strategy.ProcessOrderDefaultRecord;
import com.xvyy.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;

import java.util.*;

import com.xvyy.tingshu.common.util.MD5;
import com.xvyy.tingshu.order.adapter.PayWay;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSONObject;
import com.xvyy.tingshu.album.client.AlbumInfoFeignClient;
import com.xvyy.tingshu.common.execption.TsException;
import com.xvyy.tingshu.common.result.Result;
import com.xvyy.tingshu.model.album.AlbumInfo;
import com.xvyy.tingshu.model.album.TrackInfo;
import com.xvyy.tingshu.model.user.VipServiceConfig;
import com.xvyy.tingshu.order.helper.SignHelper;
import com.xvyy.tingshu.user.client.UserInfoFeignClient;
import com.xvyy.tingshu.user.client.VipServiceConfigFeignClient;
import com.xvyy.tingshu.vo.order.OrderDerateVo;
import com.xvyy.tingshu.vo.order.OrderDetailVo;
import com.xvyy.tingshu.vo.user.UserInfoVo;
import com.google.common.collect.Lists;

import com.xvyy.tingshu.common.util.AuthContextHolder;
import com.xvyy.tingshu.model.order.OrderInfo;
import com.xvyy.tingshu.order.mapper.OrderInfoMapper;
import com.xvyy.tingshu.order.service.OrderInfoService;
import com.xvyy.tingshu.vo.order.OrderInfoVo;
import com.xvyy.tingshu.vo.order.TradeVo;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderInfoService {

    @Autowired
    private OrderInfoMapper orderInfoMapper;
    @Autowired
    private OrderDerateMapper orderDerateMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private LocalMsgMapper localMsgMapper;
    @Autowired
    private UserInfoFeignClient userInfoFeignClient;
    @Autowired
    private AlbumInfoFeignClient albumInfoFeignClient;
    @Autowired
    private VipServiceConfigFeignClient vipServiceConfigFeignClient;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private RabbitService rabbitService;
    @Autowired
    private OrderInfoService orderInfoService;
    @Autowired
    private List<PayWay> payWayList;
    @Autowired
    private List<OrderDealTypeAdapter> orderDealTypeAdapterList;

    OrderInfoVo orderInfoVoResult = new OrderInfoVo();

    @Override
    public OrderInfoVo trade(TradeVo tradeVo) {
        // 1. 根据用户id
        Long userId = AuthContextHolder.getUserId();
        // 2. 获取付款类型
        String itemType = tradeVo.getItemType();
        // 3. 三种付款类型 "1001"专辑 "1002"声音 "1003"vip会员 策略模式优化
        for (OrderDealTypeAdapter orderDealTypeAdapter : orderDealTypeAdapterList) {
            if (orderDealTypeAdapter.supportOrderDealType(itemType)) {
                orderInfoVoResult = orderDealTypeAdapter.adapterOrderDealType(tradeVo, userId, itemType);
            }
        }
/*        orderInfoVoResult = switch (itemType) {
            case "1001" -> // 专辑
                    dealAlbumItemType(tradeVo, userId, itemType);
            case "1002" -> // 声音
                    dealTrackItemType(tradeVo, userId, itemType);
            case "1003" -> // vip会员
                    dealVipItemType(tradeVo, userId, itemType);
            default -> orderInfoVoResult;
        };*/
        // 4. 公共部前面和时间戳
        // 4.1 时间戳
        orderInfoVoResult.setTimestamp(SignHelper.getTimestamp());
        // 4.2 订单信息的签名（未来在提交订单，判断提交订单的幂等性）
        // 判断多次提交的订单是否是同一笔订单
        String sign = SignHelper.getSign(JSONObject.parseObject(JSONObject.toJSONString(orderInfoVoResult), Map.class));
        orderInfoVoResult.setSign(sign);
        if (CollectionUtils.isEmpty(orderInfoVoResult.getOrderDetailVoList())) {
            return orderInfoVoResult;
        }
        List<Long> payProductIdList = orderInfoVoResult.getOrderDetailVoList().stream().map(OrderDetailVo::getItemId).toList();
        String encrypt = MD5.encrypt(payProductIdList.toString());
        // 5. 提交订单号存入redis，防止重复提交订单
        String multipartRepeatKey = userId + ":" + encrypt;
        stringRedisTemplate.opsForValue().set(multipartRepeatKey, "1");
        // 6. 返回不同付款项的结算页数据
        return orderInfoVoResult;
    }

    @Override
    public Map<String, Object> submitOrder(OrderInfoVo orderInfoVo) {
        Long userId = AuthContextHolder.getUserId();
        // 1. 校验 （非法请求、限流、黑白名单校验、订单完整性【签名校验】）
        String tradeNo = orderInfoVo.getTradeNo();
        // 1.1 非法请求校验简单实现、如果带了trackNo
        if (StringUtils.isEmpty(tradeNo)) {
            throw new TsException(201, "非法请求");
        }
        // 1.2 签名的校验 sign值 防止订单信息被篡改
        String orderInfoStr = JSONObject.toJSONString(orderInfoVo);
        Map checkDataMap = JSONObject.parseObject(orderInfoStr, Map.class);
        checkDataMap.put("payWay", "");// payWay:{}
        SignHelper.checkSign(checkDataMap);// 校验签名是否正确，不正确抛出异常
        // 1.3 防止重复提交（订单幂等性）
        List<Long> collect = orderInfoVo.getOrderDetailVoList().stream().map(OrderDetailVo::getItemId).collect(Collectors.toList());
        String encrypt = MD5.encrypt(collect.toString());
        String checkMultiKey = userId + ":" + encrypt;
        String script = "if redis.call(\"exists\",KEYS[1])\n" + "then\n" + "    return redis.call(\"del\",KEYS[1])\n" + "else\n" + "    return 0\n" + "end";
        // redis execute方法执行脚本，返回结果为Long类型
        Long execute = stringRedisTemplate.execute(new DefaultRedisScript<Long>(script, Long.class), Arrays.asList(checkMultiKey));
        if (execute == 0) throw new TsException(ResultCodeEnum.REPEAT_SUBMIT);
        // 1.4 保存订单编号
        String orderNo = RandomStringUtils.random(15, true, false);
        // 1.6 判断支付方式，执行不同逻辑：零钱、wechat、alipay
        String payWay = orderInfoVo.getPayWay();
        // "1101 微信、1102支付宝、1103零钱"
        // 传统方案：if-else switch-case
        // 设计模式：适配器模式
        for (PayWay way : payWayList) {
            if (way.supportPayWay(payWay)) {
                way.payWay(orderInfoVo, orderNo, userId);
            }
        }
        // 3. 返回订单编号
        Map<String, Object> orderNoMap = new HashMap<>();
        orderNoMap.put("OrderNo", orderNo);
        return orderNoMap;
    }

    @Transactional(rollbackFor = Exception.class)// 开启事务 多张表
    @Override
    public OrderInfo saveOrderInfo(String orderNo, OrderInfoVo orderInfoVo, Long userId) {
        OrderInfo orderInfo = new OrderInfo();
        try {
            // 1. 保存订单基本信息
            orderInfo = saveOrderBasicInfo(orderNo, orderInfoVo, userId);
            // 2. 保存订单减免信息
            saveOrderDerateInfo(orderInfoVo, orderInfo.getId());
            // 3. 保存订单详情信息
            saveOrderDetailInfo(orderInfoVo, orderInfo.getId());
        } catch (Exception e) {
            throw new TsException(201, "服务内部出现异常，请稍后再试");//抛出异常，事务回滚
        }
        return orderInfo;
    }

    @Override
    public void saveLocalMsg(String orderNo) {
        LocalMsg localMsg = new LocalMsg();
        localMsg.setMsgContent(orderNo);
        localMsg.setStatus(0);
        localMsg.setCreateTime(new Date());
        localMsg.setUpdateTime(new Date());
        int count = localMsgMapper.insert(localMsg);
        log.info("保存订单编号到本地消息表{}", count > 0 ? "成功" : "失败");
    }

    @Override
    public void paySuccess(String orderNo) {
        // 1. 根据订单编号查询订单信息
        OrderInfo orderInfo = orderInfoService.getOrderInfo(orderNo);
        // 2. 更新订单状态
        int count = orderInfoMapper.updateOrderStatus(orderNo);
        if (count == 0) log.error("更新订单状态失败");
        else log.info("更新订单状态成功");
        // 3. MySQL记录支付
        // 获取流水信息
        UserPaidRecordVo userPaidRecordVo = prepareUserPaidRecordVo(orderInfo);
        // 3.1 发送MQ消息到user微服务，记录支付流水信息
        rabbitService.sendMessage(MqConst.EXCHANGE_USER, MqConst.ROUTING_USER_PAY_RECORD, JSONObject.toJSONString(userPaidRecordVo));
        // 4. 发送MQ消息到search微服务，更新ES中的购买量
        rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM_ES, MqConst.ROUTING_ALBUM_ES_STAT_UPDATE, orderNo);
        // 5. 发送MQ消息到album微服务，更新MySQL中的购买量
        rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM, MqConst.ROUTING_ALBUM_STAT_UPDATE, orderNo);
    }

    @Override
    public OrderInfo getOrderInfo(String orderNo) {
        // 1. 查询订单基本信息
        OrderInfo orderInfo = orderInfoMapper.selectOne(new LambdaQueryWrapper<OrderInfo>().eq(OrderInfo::getOrderNo, orderNo));
        if (orderInfo == null) {
            throw new TsException(201, "订单不存在");
        }
        // 2. 查询订单详情信息
        List<OrderDetail> orderDetailList = getOrderDetailList(orderInfo);
        orderInfo.setOrderDetailList(orderDetailList);
        // 3. 查询订单减免信息
        List<OrderDerate> orderDerateList = getOrderDerateList(orderInfo);
        orderInfo.setOrderDerateList(orderDerateList);
        // 4. 查询订单状态名字
        String orderStatus = orderInfo.getOrderStatus();
        orderInfo.setOrderStatusName(getOrderStatusName(orderStatus));
        // 5. 支付方式名字
        String payWay = orderInfo.getPayWay();
        orderInfo.setPayWayName(getPayWayName(payWay));
        // 6. 返回数据
        return orderInfo;
    }

    @Override
    public IPage<OrderInfo> findUserPage(IPage<OrderInfo> page) {
        // 1. 获取用户id
        Long userId = AuthContextHolder.getUserId();
        // 2. 获取分页参数
        IPage<OrderInfo> orderInfoIPage = page(page, new LambdaQueryWrapper<OrderInfo>()
                .eq(OrderInfo::getUserId, userId)
                .eq(OrderInfo::getIsDeleted, 0)
                .orderByDesc(OrderInfo::getCreateTime));
        // 3. 获取数据
        List<OrderInfo> orderInfoList = orderInfoIPage.getRecords();
        // 4. 遍历展示数据，组装支付方式和订单状态字段
        // orderDetailList orderDerateList orderStatusName payWayName
        orderInfoList.stream().forEach(orderInfo -> {
            String orderStatus = orderInfo.getOrderStatus();
            orderInfo.setOrderStatusName(getOrderStatusName(orderStatus));
            String payWay = orderInfo.getPayWay();
            orderInfo.setPayWayName(getPayWayName(payWay));
            List<OrderDetail> orderDetailList = getOrderDetailList(orderInfo);
            orderInfo.setOrderDetailList(orderDetailList);
            List<OrderDerate> orderDerateList = getOrderDerateList(orderInfo);
            orderInfo.setOrderDerateList(orderDerateList);
        });
        return orderInfoIPage.setRecords(orderInfoList);
    }

    /**
     * 根据订单id查询订单减免信息
     *
     * @param orderInfo
     * @return
     */
    private List<OrderDerate> getOrderDerateList(OrderInfo orderInfo) {
        return orderDerateMapper.selectList(new LambdaQueryWrapper<OrderDerate>().eq(OrderDerate::getOrderId, orderInfo.getId()));
    }

    /**
     * 根据订单id查询订单详情信息
     *
     * @param orderInfo
     * @return
     */
    private List<OrderDetail> getOrderDetailList(OrderInfo orderInfo) {
        return orderDetailMapper.selectList(new LambdaQueryWrapper<OrderDetail>().eq(OrderDetail::getOrderId, orderInfo.getId()));
    }

    /**
     * 根据订单状态获取订单状态名称
     *
     * @param orderStatus
     * @return
     */
    private String getOrderStatusName(String orderStatus) {
        return switch (orderStatus) {
            case "0901" -> "未支付";
            case "0902" -> "已支付";
            case "0903" -> "已关闭";
            default -> "";
        };
    }

    /**
     * 根据支付方式获取支付方式名称
     *
     * @return
     */
    private String getPayWayName(String payWay) {
        return switch (payWay) {
            case "1101" -> "微信支付";
            case "1102" -> "支付宝支付";
            case "1103" -> "余额支付";
            default -> "";
        };
    }

    /**
     * 准备用户支付流水信息
     *
     * @param orderInfo
     * @return
     */
    private UserPaidRecordVo prepareUserPaidRecordVo(OrderInfo orderInfo) {
        UserPaidRecordVo userPaidRecordVo = new UserPaidRecordVo();
        userPaidRecordVo.setOrderNo(orderInfo.getOrderNo());
        userPaidRecordVo.setUserId(orderInfo.getUserId());
        userPaidRecordVo.setItemType(orderInfo.getItemType());
        userPaidRecordVo.setItemIdList(orderInfo.getOrderDetailList().stream().map(OrderDetail::getItemId).collect(Collectors.toList()));
        return userPaidRecordVo;
    }

    /**
     * 保存订单详情信息
     *
     * @param orderInfoVo
     * @param orderId
     */
    private void saveOrderDetailInfo(OrderInfoVo orderInfoVo, Long orderId) {
        orderInfoVo.getOrderDetailVoList().forEach(orderDetailVo -> {
            // 1. 保存订单详情信息
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setOrderId(orderId);
            orderDetail.setItemId(orderDetailVo.getItemId());
            orderDetail.setItemName(orderDetailVo.getItemName());
            orderDetail.setItemUrl(orderDetailVo.getItemUrl());
            orderDetail.setItemPrice(orderDetailVo.getItemPrice());
            int count = orderDetailMapper.insert(orderDetail);
            log.info("保存订单详情信息到数据库{}", count > 0 ? "成功" : "失败");
        });
    }

    /**
     * 保存订单减免信息
     *
     * @param orderInfoVo
     * @param orderId
     */
    private void saveOrderDerateInfo(OrderInfoVo orderInfoVo, Long orderId) {
        orderInfoVo.getOrderDerateVoList().stream().forEach(orderDerateVo -> {
            // 1. 保存订单减免信息
            OrderDerate orderDerate = new OrderDerate();
            orderDerate.setOrderId(orderId);
            orderDerate.setDerateType(orderDerateVo.getDerateType());
            orderDerate.setDerateAmount(orderDerateVo.getDerateAmount());
            orderDerate.setRemarks(orderDerateVo.getRemarks());
            int count = orderDerateMapper.insert(orderDerate);
            log.info("保存订单减免信息到数据库{}", count > 0 ? "成功" : "失败");
        });
    }

    /**
     * 保存订单基本信息
     *
     * @param orderNo
     * @param orderInfoVo
     * @return
     */
    private OrderInfo saveOrderBasicInfo(String orderNo, OrderInfoVo orderInfoVo, Long userId) {
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setUserId(userId);
        orderInfo.setOrderTitle(orderInfoVo.getOrderDetailVoList().get(0).getItemName());
        orderInfo.setOrderNo(orderNo);
        orderInfo.setOrderStatus("0901");
        orderInfo.setOriginalAmount(orderInfoVo.getOriginalAmount());
        orderInfo.setDerateAmount(orderInfoVo.getDerateAmount());
        orderInfo.setOrderAmount(orderInfoVo.getOrderAmount());
        orderInfo.setItemType(orderInfoVo.getItemType());
        orderInfo.setPayWay(orderInfoVo.getPayWay());
        int count = orderInfoMapper.insert(orderInfo);
        log.info("保存订单基本信息到数据库{}", count > 0 ? "成功" : "失败");
        return orderInfo;
    }

    /**
     * 1001-交易类型是专辑的
     *
     * @param tradeVo
     * @param userId
     * @param itemType
     * @return
     */
    private OrderInfoVo dealAlbumItemType(TradeVo tradeVo, Long userId, String itemType) {
        // 1. 远程调用user微服务，判断是否买过该专辑
        Long albumId = tradeVo.getItemId();
        Result<Boolean> userPaidAlbumResult = userInfoFeignClient.getUserPaidAlbum(userId, albumId);
        Boolean userPaidAlbumData = userPaidAlbumResult.getData();
        Assert.notNull(userPaidAlbumData, "远程调用user微服务，判断是否买过该专辑失败");
        if (userPaidAlbumData) {
            log.error("用户{}已经购买过{}专辑，无需重复购买", userId, albumId);
            throw new TsException(201, "该付款项目已经购买过，请勿重复购买");
        }
        // 2. 判断是否在支付中
        int count = orderInfoMapper.checkAlbumAndVipTypeItemPadding(itemType, userId, albumId);
        if (count != 0) {
            log.error("该付款项专辑：{}，处于购买中，请勿继续购买该专辑", albumId);
            orderInfoVoResult.setExitItemIdList(Lists.newArrayList(albumId));
            return orderInfoVoResult;
        }
        // 3. 给OrderInfoVo赋值
        // 3.1 订单号 RandomStringUtils.random(15,true,false); : 生成15位随机字符串，字母和数字混合
        String tradeNo = RandomStringUtils.random(15, true, false);
        orderInfoVoResult.setTradeNo(tradeNo);
        // 3.2 支付方式
        orderInfoVoResult.setPayWay("");
        // 3.3 交易类型
        orderInfoVoResult.setItemType(itemType);
        // 3.4 原始金额 远程调用album微服务，在专辑信息中获取原始金额
        Result<AlbumInfo> albumInfoResult = albumInfoFeignClient.getAlbumInfo(albumId);
        AlbumInfo albumInfoData = albumInfoResult.getData();
        Assert.notNull(albumInfoData, "远程调用album微服务，获取专辑信息失败");
        BigDecimal originalAmount = albumInfoData.getPrice();
        orderInfoVoResult.setOriginalAmount(originalAmount.setScale(2, RoundingMode.HALF_UP));// 原始金额，保留两位小数，四舍五入
        // 3.5 减免金额
        // 3.5.1 远程调用user微服务，在用户付费专辑列表中获取减免金额
        Result<UserInfoVo> userInfoVoResult = userInfoFeignClient.getUserInfoVo(userId);
        UserInfoVo userInfoVoData = userInfoVoResult.getData();
        Assert.notNull(userInfoVoData, "远程调用user微服务，获取用户信息失败");
        Integer isVip = userInfoVoData.getIsVip();
        BigDecimal disCount = null;
        // 3.5.2 判断用户是否为vip会员
        if (isVip.equals("1")) {
            // 用户是vip会员
            disCount = albumInfoData.getVipDiscount();
        } else {
            // 用户不是vip会员
            disCount = albumInfoData.getDiscount();
        }
        if (disCount.intValue() == -1) {
            // 没有折扣，不打折
            disCount = new BigDecimal("10.00");
        }
        // 3.5.3 减免金额计算 = 原价格 - (原价格 * 折扣 / 10) 保留两位小数，四舍五入
        BigDecimal derateAmount = originalAmount.subtract(originalAmount.multiply(disCount).divide(new BigDecimal("10.00")));
        orderInfoVoResult.setDerateAmount(derateAmount.setScale(2, RoundingMode.HALF_UP));
        // 3.6 实付金额 = 原价格 - 减免金额 保留两位小数，四舍五入
        BigDecimal orderAmount = originalAmount.subtract(derateAmount.setScale(2, RoundingMode.HALF_UP));
        orderInfoVoResult.setOrderAmount(orderAmount.setScale(2, RoundingMode.HALF_UP));
        // 3.7 订单详情列表
        List<OrderDetailVo> orderDetailVoList = new ArrayList<>();
        OrderDetailVo orderDetailVo = new OrderDetailVo();
        orderDetailVo.setItemId(albumId);// 专辑id
        orderDetailVo.setItemName(albumInfoData.getAlbumTitle());// 专辑名称
        orderDetailVo.setItemUrl(albumInfoData.getCoverUrl());// 封面图片地址
        orderDetailVo.setItemPrice(originalAmount);// 原价
        orderDetailVoList.add(orderDetailVo);
        orderInfoVoResult.setOrderDetailVoList(Lists.newArrayList(orderDetailVoList));
        // 3.8 订单减免列表
        List<OrderDerateVo> orderDerateVoList = new ArrayList<>();
        OrderDerateVo orderDerateVo = new OrderDerateVo();
        orderDerateVo.setDerateType("专辑折扣");// 折扣类型
        orderDerateVo.setDerateAmount(derateAmount.setScale(2, RoundingMode.HALF_UP));// 折扣：10.00，
        orderDerateVo.setRemarks("订单减免类型专辑折扣减免");// 备注信息
        orderDerateVoList.add(orderDerateVo);
        orderInfoVoResult.setOrderDerateVoList(Lists.newArrayList(orderDerateVoList));
        // 4. 返回结果
        return orderInfoVoResult;
    }

    /**
     * 1002-交易类型是声音
     *
     * @param tradeVo
     * @param userId
     * @param itemType
     * @return
     */
    private OrderInfoVo dealTrackItemType(TradeVo tradeVo, Long userId, String itemType) {
        Long trackId = tradeVo.getItemId();
        // 1. 幂等性判断 判断是否买过该声音
        Integer trackCount = tradeVo.getTrackCount();
        Result<TrackInfo> trackInfoResult = albumInfoFeignClient.getTrackInfoById(trackId);
        TrackInfo trackInfoData = trackInfoResult.getData();
        Assert.notNull(trackInfoData, "远程调用album微服务，获取声音信息失败");
        Long albumId = trackInfoData.getAlbumId();
        Result<AlbumInfo> albumInfoResult = albumInfoFeignClient.getAlbumInfo(albumId);
        AlbumInfo albumInfoData = albumInfoResult.getData();
        Assert.notNull(albumInfoData, "远程调用album微服务，获取专辑信息失败");
        // 2. 幂等性校验综合方法，判断是否在支付中，查询声音并过滤购买过的声音
        Result<List> canPayTrackList = albumInfoFeignClient.getPaidTrackAndFilterCanPayTrack(albumId, userId, trackCount, trackId);
        Integer code = canPayTrackList.getCode();
        // 2.1 判断是否买过该声音
        if (code == 400) {
            // 返回买过的声音
            List data = canPayTrackList.getData();
            orderInfoVoResult.setExitItemIdList(data);
            return orderInfoVoResult;
        }
        // 2.2 判断能买的声音列表
        List<Map> canPayTrackListData = canPayTrackList.getData();
        Assert.notNull(canPayTrackListData, "远程调用album微服务，声音列表失败");
        // 2.3 判断是否在支付中 优化将正在支付的错误信息返回给前端
        List<Long> paidTrackIdList = orderInfoMapper.checkTrackTypeItemPadding(itemType, userId);
        List<Map> paddingTrackMapList = canPayTrackListData.stream().filter(map -> paidTrackIdList.contains(map.get("id"))).collect(Collectors.toList());
        List<Object> exitItemIdList = new ArrayList<>();
        // 2.4 判断是否在支付中
        if (!CollectionUtils.isEmpty(paddingTrackMapList)) {
            // 2.4.1 在支付中
            for (Map map : paddingTrackMapList) {
                exitItemIdList.add(map.get("id"));
                log.error("该付款项声音：{}，处于购买中，请勿继续购买该声音", map.get("id"));
            }
            // 返回给前端
            orderInfoVoResult.setExitItemIdList(exitItemIdList);
            return orderInfoVoResult;
        }
        // 2.4.2 不在支付中，可以继续购买
        // 3. 给OrderInfoVo赋值
        // 3.1 订单号
        String tradeNo = RandomStringUtils.random(12, true, true);
        orderInfoVoResult.setTradeNo(tradeNo);
        // 3.2 支付方式
        orderInfoVoResult.setPayWay("");
        // 3.3 交易类型
        orderInfoVoResult.setItemType(itemType);
        // 3.4 原始金额
        BigDecimal trackPrice = albumInfoData.getPrice();
        BigDecimal originalAmount = trackCount == 0 ? trackPrice : trackPrice.multiply(new BigDecimal(trackCount));
        orderInfoVoResult.setOriginalAmount(originalAmount.setScale(2, RoundingMode.HALF_UP));
        // 3.5 减免金额
        orderInfoVoResult.setDerateAmount(new BigDecimal("0.00").setScale(2, RoundingMode.HALF_UP));
        // 3.6 实付金额
        orderInfoVoResult.setOrderAmount(originalAmount.setScale(2, RoundingMode.HALF_UP));
        // 3.7 订单详情列表
        ArrayList<OrderDetailVo> orderDetailVoList = new ArrayList<>();
        for (Map map : canPayTrackListData) {
            OrderDetailVo orderDetailVo = new OrderDetailVo();
            Object id = map.get("id");
            orderDetailVo.setItemId(Long.parseLong(id + ""));
            orderDetailVo.setItemName((String) map.get("trackTitle"));
            orderDetailVo.setItemUrl((String) map.get("coverUrl"));
            orderDetailVo.setItemPrice(trackPrice.setScale(2, RoundingMode.HALF_UP));
            orderDetailVoList.add(orderDetailVo);
        }
        orderInfoVoResult.setOrderDetailVoList(Lists.newArrayList(orderDetailVoList));
        // 3.8 订单减免列表
        orderInfoVoResult.setOrderDerateVoList(Lists.newArrayList());//声音不打折
        // 4. 返回结果
        return orderInfoVoResult;
    }

    /**
     * 1003-交易类型是vip会员
     *
     * @param tradeVo
     * @param userId
     * @param itemType
     * @return
     */
    private OrderInfoVo dealVipItemType(TradeVo tradeVo, Long userId, String itemType) {

        // 1. 获取itemId
        Long itemId = tradeVo.getItemId();
        int count = orderInfoMapper.checkAlbumAndVipTypeItemPadding(itemType, userId, itemId);
        if (count != 0) {
            log.error("该付款项声音：{}，处于购买中，请勿继续购买该声音", itemId);
            orderInfoVoResult.setExitItemIdList(Lists.newArrayList(itemId));
            return orderInfoVoResult;
        }
        // 3. 给OrderInfoVo赋值
        // 3.1 订单号
        String tradeNo = RandomStringUtils.random(12, true, true);
        orderInfoVoResult.setTradeNo(tradeNo);
        // 3.2 支付方式
        orderInfoVoResult.setPayWay("");
        // 3.3 交易类型
        orderInfoVoResult.setItemType(itemType);
        // 3.4 原始金额
        Result<VipServiceConfig> vipServiceConfigResult = vipServiceConfigFeignClient.getAllVipConfig(itemId);
        VipServiceConfig vipServiceConfigData = vipServiceConfigResult.getData();
        Assert.notNull(vipServiceConfigData, "远程调用vip微服务，获取会员配置失败");
        BigDecimal originalAmount = vipServiceConfigData.getPrice();
        orderInfoVoResult.setOriginalAmount(originalAmount.setScale(2, RoundingMode.HALF_UP));
        BigDecimal orderAmount = vipServiceConfigData.getDiscountPrice();
        BigDecimal derateAmount = originalAmount.subtract(orderAmount);
        // 3.5 减免金额
        orderInfoVoResult.setDerateAmount(derateAmount.setScale(2, RoundingMode.HALF_UP));
        // 3.6 实付金额
        orderInfoVoResult.setOrderAmount(orderAmount.setScale(2, RoundingMode.HALF_UP));
        // 3.7 订单详情列表
        List<OrderDetailVo> orderDetailVoList = new ArrayList<>();
        OrderDetailVo orderDetailVo = new OrderDetailVo();
        orderDetailVo.setItemId(itemId);
        orderDetailVo.setItemName(vipServiceConfigData.getName());
        orderDetailVo.setItemUrl(vipServiceConfigData.getImageUrl());
        orderDetailVo.setItemPrice(orderAmount.setScale(2, RoundingMode.HALF_UP));
        orderDetailVoList.add(orderDetailVo);
        orderInfoVoResult.setOrderDetailVoList(Lists.newArrayList(orderDetailVoList));
        // 3.8 订单减免列表
        ArrayList<OrderDerateVo> orderDerateVoList = new ArrayList<>();
        OrderDerateVo orderDerateVo = new OrderDerateVo();
        orderDerateVo.setDerateType("VIP服务折扣");
        orderDerateVo.setDerateAmount(derateAmount);
        orderDerateVo.setRemarks("订单减免类型1406-VIP服务折扣");
        orderDerateVoList.add(orderDerateVo);
        orderInfoVoResult.setOrderDerateVoList(Lists.newArrayList(orderDerateVoList));
        // 4. 返回结果
        return orderInfoVoResult;
    }

}
